package com.hbx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbx.auth.AuthCacheService;
import com.hbx.constant.CachePrefixContent;
import com.hbx.dto.pk.InsertPkDto;
import com.hbx.dto.pk.SearchDto;
import com.hbx.exception.RspException;
import com.hbx.model.Pk;
import com.hbx.mapper.PkMapper;
import com.hbx.model.PkResult;
import com.hbx.model.Rank;
import com.hbx.model.User;
import com.hbx.service.PkResultService;
import com.hbx.service.PkService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbx.service.RankService;
import com.hbx.service.UserService;
import com.hbx.utils.CacheUtils;
import com.hbx.utils.Result;
import com.hbx.vo.PageBean;
import com.hbx.vo.PublicUserVo;
import com.hbx.vo.RankVo;
import com.hbx.vo.pk.MyPkVo;
import com.hbx.vo.pk.PkDetailVo;
import com.hbx.vo.pk.PkIntemVo;
import com.hbx.vo.pk.PkResultVo;
import com.hbx.vo.res.MyResVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hbx
 * @since 2022-01-29
 */
@Service
@Slf4j
public class PkServiceImpl extends ServiceImpl<PkMapper, Pk> implements PkService {

    @Autowired
    private PkMapper pkMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RankService rankService;

    @Autowired
    private PkResultService pkResultService;
    
    @Autowired
    private CacheUtils cacheUtils;


    /**
     * 发布pk
     * @param dto
     * @param r
     */
    @Override
    public void insertPk(InsertPkDto dto, Result r) {
        User user = AuthCacheService.getUser();
        Pk pk = new Pk();
        BeanUtils.copyProperties(dto, pk);
        pk.setPkPublishTime(new Date());
        pk.setPkPublicUserId(user.getUserId());
        pk.setPkDelete(0);
        int result = pkMapper.insert(pk);
        if (result != 1){
            throw new RspException(201, "pk发布失败");
        }
        r.setCode(200).setMsg("发布成功");
    }

    /**
     * 获取pk列表
     * @param dto
     * @param r
     */
    @Override
    public void searchList(SearchDto dto, Result r) {
        String keyword = dto.getKeyword();
        Page<Pk> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        PageBean result = new PageBean();
        QueryWrapper<Pk> wrapper = new QueryWrapper<>();
        if (StringUtils.hasLength(keyword)){
            wrapper.like("pk_title", keyword).or().like("pk_content", keyword);
        }
        wrapper.eq("pk_delete",0);
        wrapper.orderByDesc("pk_publish_time");
        IPage<Pk> pkIPage = pkMapper.selectPage(page, wrapper);
        result.setTotal(pkIPage.getTotal());
        result.setPageNum(pkIPage.getCurrent());
        result.setPageSize(pkIPage.getSize());
        List<Pk> records = pkIPage.getRecords();
        if (CollectionUtils.isEmpty(records)){
            result.setData(new ArrayList<>());
            r.setCode(201).setData(result);
            return;
        }
        List<PkIntemVo> voList = new ArrayList<>();
        records.stream().forEach(record -> {
            PkIntemVo item = new PkIntemVo();
            BeanUtils.copyProperties(record, item);
            if (record.getPkPublicUserId() != null){
                PublicUserVo userVo = new PublicUserVo();
                User user = userService.getById(record.getPkPublicUserId());
                if (user != null){
                    List<Rank> rankList = rankService.getRankList(user.getUserId());
                    userVo.setUserId(user.getUserId());
                    userVo.setUserName(user.getLoginName());
                    userVo.setAvatar(user.getAvator());
                    if (rankList != null){
                        List<RankVo> list = new ArrayList<>();
                        rankList.stream().forEach(rank -> {
                            RankVo rankVo = new RankVo();
                            BeanUtils.copyProperties(rank, rankVo);
                            list.add(rankVo);
                        });
                        userVo.setRankList(list);
                    }
                }
                item.setUser(userVo);
            }
            // 设置支持反对数
            QueryWrapper<PkResult> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pk_id",record.getId());
            List<PkResult> pkResults = pkResultService.list(queryWrapper);
            if (CollectionUtils.isEmpty(pkResults)){
                item.setFNiu(0);
                item.setZNiu(0);
                item.setCount(0);
            } else {
                item.setCount(pkResults.size());
                Map<Integer, List<PkResult>> listMap = pkResults.stream().collect(Collectors.groupingBy(PkResult::getResultType));
                if (listMap != null){
                    List<PkResult> zResults = listMap.get(1);
                    List<PkResult> fResults = listMap.get(2);
                    if (zResults != null){
                        item.setZNiu(zResults.size());
                    }
                    if (fResults != null){
                        item.setFNiu(fResults.size());
                    }
                }
            }
            voList.add(item);
        });
        result.setData(voList);
        r.setCode(200).setData(result);
    }

    /**
     * 查询我的pk
     * @param pageSize
     * @param userId
     * @param r
     */
    @Override
    public void getMyPk(Integer pageSize, Integer userId, Result<MyResVo> r) {
        // 查询博客
        User user = userService.getById(userId);
        List<MyPkVo> voList = new ArrayList<>();
        if (user == null){
            log.error("【系统提示】:用户信息已失效");
            r.setCode(201).setMsg("用户信息不存在");
            return;
        }
        Page<Pk> page = new Page(0, pageSize);
        QueryWrapper<Pk> wrapper = new QueryWrapper();
        wrapper.eq("pk_public_user_id",user.getUserId());
        wrapper.orderByDesc("pk_publish_time");
        wrapper.eq("pk_delete",0);

        IPage<Pk> pkIPage = pkMapper.selectPage(page, wrapper);
        List<Pk> pkList = pkIPage.getRecords();
        if (CollectionUtils.isEmpty(pkList)){
            r.setCode(200).setData(new ArrayList<>());
            return;
        }
        pkList.stream().forEach(pk -> {
            MyPkVo item = new MyPkVo();
            BeanUtils.copyProperties(pk, item);
            // 设置支持反对数
            QueryWrapper<PkResult> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pk_id",pk.getId());
            List<PkResult> pkResults = pkResultService.list(queryWrapper);
            if (CollectionUtils.isEmpty(pkResults)){
                item.setFNiu(0);
                item.setZNiu(0);
                item.setCount(0);
            } else {
                item.setCount(pkResults.size());
                Map<Integer, List<PkResult>> listMap = pkResults.stream().collect(Collectors.groupingBy(PkResult::getResultType));
                if (listMap != null) {
                    List<PkResult> zResults = listMap.get(1);
                    List<PkResult> fResults = listMap.get(2);
                    if (zResults != null) {
                        item.setZNiu(zResults.size());
                    }
                    if (fResults != null) {
                        item.setFNiu(fResults.size());
                    }
                }
            }
            voList.add(item);
        });
        r.setCode(200).setData(voList);
    }

    /**
     * 删除我的pk
     * @param id
     * @param r
     */
    @Override
    @Transactional
    public void removePk(Integer id, Result r) {
        User user = AuthCacheService.getUser();
        Pk pk = pkMapper.selectById(id);
        if (pk == null){
            r.setCode(201).setMsg("pk不存在,请重新加载页面");
            return;
        }
        if (!user.getUserId().equals(pk.getPkPublicUserId())){
            r.setCode(201).setMsg("非法操作,删除失败");
            return;
        }
        int result = pkMapper.deleteById(id);
        if (result == 1){
            // 删除旗下所有观点
            QueryWrapper<PkResult> wrapper = new QueryWrapper<>();
            wrapper.eq("pk_id", id);
            pkResultService.remove(wrapper);
            r.setCode(200).setMsg("删除成功");
            return;
        }
        r.setCode(201).setMsg("删除失败");
    }

    /**
     * 获得Pk详情
     * @param id
     * @param r
     */
    @Override
    public void getPkInfo(Integer id, Result r) {
        User currentUser = AuthCacheService.getUser();
        PkDetailVo vo = new PkDetailVo();
        Pk pk = pkMapper.selectById(id);
        if (pk == null){
            r.setCode(201).setMsg("pk信息不存在");
            return;
        }
        BeanUtils.copyProperties(pk, vo);
        // 设置发布人信息
        User user = userService.getById(pk.getPkPublicUserId());
        if (user != null){
            PublicUserVo userVo = new PublicUserVo();
            userVo.setUserId(user.getUserId());
            userVo.setType(user.getType());
            userVo.setUserName(user.getLoginName());
            userVo.setAvatar(user.getAvator());
            List<Rank> rankList = rankService.getRankList(user.getUserId());
            if (!CollectionUtils.isEmpty(rankList)){
                List<RankVo> list = new ArrayList<>();
                rankList.stream().forEach(rank -> {
                    RankVo rankVo = new RankVo();
                    BeanUtils.copyProperties(rank, rankVo);
                    list.add(rankVo);
                });
                userVo.setRankList(list);
            }
            vo.setPkUser(userVo);
        }

        // 查询对应观点信息
        QueryWrapper<PkResult> wrapper = new QueryWrapper<>();
        wrapper.eq("pk_id",pk.getId());
        List<PkResult> pkResults = pkResultService.list(wrapper);
        if (CollectionUtils.isEmpty(pkResults)){
            r.setCode(200).setData(vo);
            return;
        }
        Map<Integer, List<PkResult>> zfMap = pkResults
                .stream()
                .collect(Collectors.groupingBy(PkResult::getResultType));
        List<PkResult> zResults = zfMap.get(1);
        List<PkResult> fResults = zfMap.get(2);
        if (!CollectionUtils.isEmpty(zResults)){
            List<PkResultVo> zResultList = new ArrayList<>();
            zResults.stream().forEach(zResult -> {
                PkResultVo resultVo = new PkResultVo();
                BeanUtils.copyProperties(zResult, resultVo);
                User zUser = userService.getById(zResult.getResultUserId());
                if (zUser != null){
                    PublicUserVo userVo = new PublicUserVo();
                    userVo.setUserId(zUser.getUserId());
                    userVo.setType(zUser.getType());
                    userVo.setUserName(zUser.getLoginName());
                    userVo.setAvatar(zUser.getAvator());
                    List<Rank> rankList = rankService.getRankList(zUser.getUserId());
                    if (!CollectionUtils.isEmpty(rankList)){
                        List<RankVo> list = new ArrayList<>();
                        rankList.stream().forEach(rank -> {
                            RankVo rankVo = new RankVo();
                            BeanUtils.copyProperties(rank, rankVo);
                            list.add(rankVo);
                        });
                        userVo.setRankList(list);
                    }
                    resultVo.setResultUser(userVo);
                }
                Set<Object> members = cacheUtils.getSetMembers(CachePrefixContent.PLAT_PK_RESULT_NIU_INFO + zResult.getId());
                if (CollectionUtils.isEmpty(members)){
                    resultVo.setResultIsNiu(0);
                } else {
                    if (members.contains(currentUser.getUserId())){
                        resultVo.setResultIsNiu(1);
                    }else {
                        resultVo.setResultIsNiu(0);
                    }
                }
                zResultList.add(resultVo);
            });
            vo.setZList(zResultList);
        }

        if (!CollectionUtils.isEmpty(fResults)){
            List<PkResultVo> fResultList = new ArrayList<>();
            fResults.stream().forEach(fResult -> {
                PkResultVo resultVo = new PkResultVo();
                BeanUtils.copyProperties(fResult, resultVo);
                User fUser = userService.getById(fResult.getResultUserId());
                if (fUser != null){
                    PublicUserVo userVo = new PublicUserVo();
                    userVo.setUserId(fUser.getUserId());
                    userVo.setType(fUser.getType());
                    userVo.setUserName(fUser.getLoginName());
                    userVo.setAvatar(fUser.getAvator());
                    List<Rank> rankList = rankService.getRankList(fUser.getUserId());
                    if (!CollectionUtils.isEmpty(rankList)){
                        List<RankVo> list = new ArrayList<>();
                        rankList.stream().forEach(rank -> {
                            RankVo rankVo = new RankVo();
                            BeanUtils.copyProperties(rank, rankVo);
                            list.add(rankVo);
                        });
                        userVo.setRankList(list);
                    }
                    resultVo.setResultUser(userVo);
                }
                Set<Object> members = cacheUtils.getSetMembers(CachePrefixContent.PLAT_PK_RESULT_NIU_INFO + fResult.getId());
                if (CollectionUtils.isEmpty(members)){
                    resultVo.setResultIsNiu(0);
                } else {
                    if (members.contains(currentUser.getUserId())){
                        resultVo.setResultIsNiu(1);
                    }else {
                        resultVo.setResultIsNiu(0);
                    }
                }
                fResultList.add(resultVo);
            });
            vo.setFList(fResultList);
        }
        r.setCode(200).setData(vo);
    }
}
